package com.electromagnetic.industry.software.manage.service.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.electromagnetic.industry.software.common.enums.EffectFlagEnum;
import com.electromagnetic.industry.software.common.pojo.RespPageVO;
import com.electromagnetic.industry.software.common.resp.ElectromagneticResult;
import com.electromagnetic.industry.software.common.util.EleCommonUtil;
import com.electromagnetic.industry.software.common.util.ElectromagneticResultUtil;
import com.electromagnetic.industry.software.common.util.EleIdCreator;
import com.electromagnetic.industry.software.manage.mapper.ImportTableDataMapper;
import com.electromagnetic.industry.software.manage.mapper.ImportTableInfoMapper;
import com.electromagnetic.industry.software.manage.pojo.models.ImportTableData;
import com.electromagnetic.industry.software.manage.pojo.models.ImportTableInfo;
import com.electromagnetic.industry.software.manage.pojo.req.DownloadImportTableDataDTO;
import com.electromagnetic.industry.software.manage.pojo.resp.ImportTablePageDataVO;
import com.electromagnetic.industry.software.manage.service.ImportTableService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class ImportTableServiceImpl implements ImportTableService {

    @Resource
    private ImportTableDataMapper importTableDataMapper;
    @Resource
    private ImportTableInfoMapper importTableInfoMapper;

    @Override
    public String addTableInfo(String relatedId, Map<Integer, Object> tableHeader) {
        String id = EleIdCreator.createSnowflakeId();
        ImportTableInfo importTableInfo = new ImportTableInfo()
                .setId(id)
                .setTableHeader(JSONUtil.toJsonStr(tableHeader))
                .setRelatedId(relatedId);
        importTableInfoMapper.insert(importTableInfo);
        return id;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ElectromagneticResult<?> removeTableInfoByRelatedId(String relatedId) {
        // 删除table_info相关信息
        LambdaQueryWrapper<ImportTableInfo> wrapper = Wrappers.lambdaQuery(ImportTableInfo.class)
                .select(ImportTableInfo::getId)
                .eq(ImportTableInfo::getRelatedId, relatedId)
                .eq(ImportTableInfo::getEffectFlag, EffectFlagEnum.EFFECT.code);
        List<String> ids = importTableInfoMapper.selectList(wrapper).stream().map(ImportTableInfo::getId).toList();
        if (CollUtil.isEmpty(ids)) {
            return ElectromagneticResultUtil.success(true);
        }
        importTableInfoMapper.update(new ImportTableInfo(), Wrappers.<ImportTableInfo>lambdaUpdate()
                .set(ImportTableInfo::getEffectFlag, EffectFlagEnum.NOT_EFFECTIVE.code)
                .in(ImportTableInfo::getId, ids));
        // 删除table_data相关信息
        importTableDataMapper.update(new ImportTableData(), Wrappers.<ImportTableData>lambdaUpdate()
                .in(ImportTableData::getTableInfoId, ids)
                .set(ImportTableData::getEffectFlag, EffectFlagEnum.EFFECT.code));
        return ElectromagneticResultUtil.success(true);
    }

    @Override
    public ImportTableInfo selectByIdRelatedId(String relatedId) {
        return importTableInfoMapper.selectOne(Wrappers.<ImportTableInfo>lambdaQuery()
                .eq(ImportTableInfo::getRelatedId, relatedId)
                .eq(ImportTableInfo::getEffectFlag, EffectFlagEnum.EFFECT.code));
    }

    @Override
    public ElectromagneticResult<?> removeTableInfoById(String id) {
        importTableInfoMapper.update(new ImportTableInfo(), Wrappers.<ImportTableInfo>lambdaUpdate()
                .set(ImportTableInfo::getEffectFlag, EffectFlagEnum.NOT_EFFECTIVE.code)
                .eq(ImportTableInfo::getId, id));
        importTableDataMapper.update(new ImportTableData(), Wrappers.<ImportTableData>lambdaUpdate()
                .eq(ImportTableData::getTableInfoId, id)
                .set(ImportTableData::getEffectFlag, EffectFlagEnum.EFFECT.code));
        return ElectromagneticResultUtil.success(true);
    }

    @Override
    public ElectromagneticResult<?> updateTableInfo() {
        return ElectromagneticResultUtil.success(true);
    }

    @Override
    public ElectromagneticResult<?> selectTableInfoByRelatedId(String relatedId) {

        return null;
    }

    @Override
    public String addTableData(String tableInfoId, String tableData) {
        String id = EleIdCreator.createSnowflakeId();
        ImportTableData importTableData = new ImportTableData().setId(id).setTableInfoId(tableInfoId).setData(tableData);
        importTableDataMapper.insert(importTableData);
        return id;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ElectromagneticResult<?> removeTableDataById(String id) {
        importTableDataMapper.update(new ImportTableData(), Wrappers.<ImportTableData>lambdaUpdate()
                .eq(ImportTableData::getId, id)
                .set(ImportTableData::getEffectFlag, EffectFlagEnum.NOT_EFFECTIVE.code));
        return ElectromagneticResultUtil.success(true);
    }

    @Override
    public ElectromagneticResult<?> updateTableData(String id, String tableHeader) {
        importTableDataMapper.update(new ImportTableData(), Wrappers.<ImportTableData>lambdaUpdate()
                .eq(ImportTableData::getId, id)
                .set(ImportTableData::getData, tableHeader));
        return ElectromagneticResultUtil.success(true);
    }

    @Override
    public RespPageVO selectTableDataByTableInfoId(Integer pageNum, Integer pageSize, String tableInfoId) {
        Page<ImportTableData> importTableData = importTableDataMapper.selectPage(new Page<>(pageNum, pageSize), Wrappers.lambdaQuery(ImportTableData.class)
                .eq(ImportTableData::getTableInfoId, tableInfoId)
                .eq(ImportTableData::getEffectFlag, EffectFlagEnum.EFFECT.code)
                .orderByAsc(ImportTableData::getCreatedTime));
        long total = importTableData.getTotal();
        if (0 == total) {
            return new RespPageVO<>(total, List.of());
        }
        List<ImportTablePageDataVO> pageVo = BeanUtil.copyToList(importTableData.getRecords(), ImportTablePageDataVO.class);
        return new RespPageVO<>(total, pageVo);
    }

    @Override
    public ResponseEntity<byte[]> downloadTableData(DownloadImportTableDataDTO downloadImportTableDataDTO, HttpServletResponse response) {
        String nowTimeStr = EleCommonUtil.getNowTimeStr();
        String attachement = StrFormatter.format("attachement; filename={}.json", nowTimeStr);
        List<String> selectIds = downloadImportTableDataDTO.getIds();
        List<ImportTableData> importTableData = importTableDataMapper.selectList(Wrappers.<ImportTableData>lambdaQuery().select(ImportTableData::getTableInfoId, ImportTableData::getData).in(ImportTableData::getId, selectIds));

        if (CollUtil.isEmpty(importTableData)) {
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, attachement)
                    .contentType(MediaType.APPLICATION_OCTET_STREAM)
                    .contentLength(0)
                    .body("".getBytes());
        }

        String tableInfoId = importTableData.get(0).getTableInfoId();
        ImportTableInfo importTableInfo = importTableInfoMapper.selectById(tableInfoId);
        Map<String, Object> map = new HashMap<>();
        map.put("header", importTableInfo.getTableHeader());
        map.put("data", importTableData);
        byte[] data = JSONUtil.toJsonStr(map).getBytes(Charset.defaultCharset());
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, attachement)
                .contentType(MediaType.APPLICATION_OCTET_STREAM)
                .contentLength(data.length)
                .body(data);
    }

}
